/*
 * Copyright 2018-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *     http://aws.amazon.com/apache2.0/
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

#include "LocalMediaSourceDispatcher.h"

#include <json-c/json.h>

#include <aasb/Consts.h>

#include "AlexaConsts.h"

namespace agl {
namespace dispatcher {
namespace localmediasource {

// Shortcut to reach logging level.
using Level = agl::common::interfaces::ILogger::Level;

// Namespaces.
using namespace agl::common::interfaces;
using namespace aasb::bridge;

// Logging Tag for this file.
static std::string TAG = "alexa::plugins::LocalMediaSourceDispatcher";

// Name of the localmediasource capability
static std::string VSHL_CAPABILITY_LOCAL_MEDIA_SOURCE = "localmediasource";

// LocalMediaSource publish verb to notify vshl capabilities of new event/directive generated by Alexa.
static std::string VSHL_CAPABILITY_VERB_LOCAL_MEDIA_SOURCE_PUBLISH = VSHL_CAPABILITY_LOCAL_MEDIA_SOURCE + "/publish";

// LocalMediaSource subscribe verb to subscribe for vshl capabilities events from Apps.
static std::string VSHL_CAPABILITY_VERB_LOCAL_MEDIA_SOURCE_SUBSCRIBE = VSHL_CAPABILITY_LOCAL_MEDIA_SOURCE + "/subscribe";

std::shared_ptr<LocalMediaSourceDispatcher> LocalMediaSourceDispatcher::create(
    std::shared_ptr<ILogger> logger,
    std::shared_ptr<IAASBController> aasbController,
    std::shared_ptr<IAFBApi> api) {

    return std::shared_ptr<LocalMediaSourceDispatcher>(new LocalMediaSourceDispatcher(logger, aasbController, api));
}

LocalMediaSourceDispatcher::LocalMediaSourceDispatcher(
    std::shared_ptr<ILogger> logger,
    std::shared_ptr<IAASBController> aasbController,
    std::shared_ptr<IAFBApi> api) :
        m_logger(logger),
        m_aasbController(aasbController),
        m_api(api) {
}

void LocalMediaSourceDispatcher::onReceivedDirective(
    const std::string& action,
    const std::string& payload) {

    m_logger->log(Level::DEBUG, TAG, "Processing localmediasource directive: " + action);

    std::string vshlCapabilityAction = action;

    json_object* argsJ = json_object_new_object();
    json_object* actionJ = json_object_new_string(vshlCapabilityAction.c_str());
    json_object* payloadJ = json_object_new_string(payload.c_str());
    json_object_object_add(argsJ, agl::alexa::JSON_ATTR_ACTION.c_str(), actionJ);
    json_object_object_add(argsJ, agl::alexa::JSON_ATTR_PAYLOAD.c_str(), payloadJ);

    auto logger = m_logger;  // To capture it for the lambda.
    m_api->callAsync(
        agl::alexa::VSHL_CAPABILITIES_API_NAME,
        VSHL_CAPABILITY_VERB_LOCAL_MEDIA_SOURCE_PUBLISH,
        argsJ,
        [logger](json_object* result, const std::string err, const std::string info) {
            logger->log(Level::DEBUG, TAG, "LocalMediaSource publish completed err:" + err);
        });

    m_logger->log(Level::DEBUG, TAG, "LocalMediaSource action processing completed");
}

bool LocalMediaSourceDispatcher::subscribeToLocalMediaSourceEvents() {
    m_logger->log(Level::INFO, TAG, "Subscribing to localmediasource control capabilities");

    json_object *argsJ = json_object_new_object();
    json_object *actionsJ = json_object_new_array();
    json_object_array_add(actionsJ, json_object_new_string(aasb::bridge::ACTION_LOCAL_MEDIA_SOURCE_GET_STATE_RESPONSE.c_str()));

    json_object_object_add(argsJ, agl::alexa::JSON_ATTR_ACTIONS.c_str(), actionsJ);

    json_object* response = NULL;
    std::string error, info;
    int result = m_api->callSync(
        agl::alexa::VSHL_CAPABILITIES_API_NAME,
        VSHL_CAPABILITY_VERB_LOCAL_MEDIA_SOURCE_SUBSCRIBE,
        argsJ,
        &response,
        error,
        info);
    if (result != 0) {
        m_logger->log(Level::ERROR, TAG, "Failed to subscribe to localmediasource control capabilities. Error: " + error);
    }

    if (response != NULL) {
        json_object_put(response);
    }

    return result == 0;
}

void LocalMediaSourceDispatcher::onGetStateResponse(const std::string& payload) {
    m_aasbController->onReceivedEvent(
        TOPIC_LOCAL_MEDIA_SOURCE,
        ACTION_LOCAL_MEDIA_SOURCE_GET_STATE_RESPONSE,
        payload);
}

void LocalMediaSourceDispatcher::onPlayerEvent(const std::string& payload) {
    m_aasbController->onReceivedEvent(
        TOPIC_LOCAL_MEDIA_SOURCE,
        ACTION_LOCAL_MEDIA_SOURCE_PLAYER_EVENT,
        payload);
}

void LocalMediaSourceDispatcher::onPlayerError(const std::string& payload) {
    m_aasbController->onReceivedEvent(
        TOPIC_LOCAL_MEDIA_SOURCE,
        ACTION_LOCAL_MEDIA_SOURCE_PLAYER_ERROR,
        payload);
}

}  // namespace localmediasource
}  // namespace dispatcher
}  // namespace agl
